// ChartPointsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "LightspeedTraderAPIDemo.h"
#include "ChartPointsDlg.h"

// ChartPointsDlg dialog

IMPLEMENT_DYNAMIC(ChartPointsDlg, CModelessDialog)

ChartPointsDlg::ChartPointsDlg(CWnd* pParent /*=NULL*/)
	: CModelessDialog(ChartPointsDlg::IDD, pParent)
	, summary(NULL)
	, m_Linked(false)
{

}

ChartPointsDlg::~ChartPointsDlg()
{
	if (summary)
	{
		summary->L_Detach(this);
		L_DestroySummary(summary);
	}
}

BOOL ChartPointsDlg::Create(CWnd *pParentWnd /*= CWnd::FromHandle(L_GetMainWnd())*/)
{
	return __super::Create(ChartPointsDlg::IDD, pParentWnd);
}

void ChartPointsDlg::DoDataExchange(CDataExchange* pDX)
{
	__super::DoDataExchange(pDX);

	DDX_Control(pDX, IDC_SYMBOLEDIT, m_SymbolEdit);
	DDX_Control(pDX, IDC_CHARTPOINTSLIST, m_ChartPointsListCtrl);
}

BOOL ChartPointsDlg::OnInitDialog()
{
	__super::OnInitDialog();

	DWORD style = m_ChartPointsListCtrl.GetExtendedStyle();
	style |= LVS_EX_FULLROWSELECT;
	style |= LVS_EX_GRIDLINES;
	style |= LVS_EX_DOUBLEBUFFER;
	m_ChartPointsListCtrl.SetExtendedStyle(style);

	m_ChartPointsListCtrl.InsertColumn(0, "Time", LVCFMT_LEFT, 70);
	m_ChartPointsListCtrl.InsertColumn(1, "Open", LVCFMT_RIGHT, 50);
	m_ChartPointsListCtrl.InsertColumn(2, "High", LVCFMT_RIGHT, 50);
	m_ChartPointsListCtrl.InsertColumn(3, "Low", LVCFMT_RIGHT, 50);
	m_ChartPointsListCtrl.InsertColumn(4, "Close", LVCFMT_RIGHT, 50);
	m_ChartPointsListCtrl.InsertColumn(5, "Volume", LVCFMT_LEFT, 60);

	L_AttachToAppNotifier(this);

	return TRUE;
}

void ChartPointsDlg::OnOK()
{
	CString symbol;
	m_SymbolEdit.GetWindowText(symbol);
	symbol.Trim();
	if (! symbol.IsEmpty())
	{
		SetSymbol(symbol.GetBuffer());

		if (m_Linked)
		{
			L_SetFocusedSymbol(symbol.GetBuffer());
		}
	}
}

void ChartPointsDlg::SetSymbol(const char *symbol)
{
	if (summary)
	{
		summary->L_Detach(this);
		L_DestroySummary(summary);
	}

	m_SymbolEdit.SetWindowText(symbol);

	summary = L_CreateSummary(symbol);
	summary->L_Attach(this);

	InsertInitialChart();
}

void ChartPointsDlg::InsertInitialChart()
{
	if (summary)
	{
		L_Chart *chart = summary->L_GetChart();

		if (chart->L_NumPoints() > 1) //make sure i have chart points older than the current minute
		{
			L_ChartPoint const *point;
			CString text;

			m_ChartPointsListCtrl.SetRedraw(FALSE);

			while (m_ChartPointsListCtrl.GetItemCount() > 0)
			{
				m_ChartPointsListCtrl.DeleteItem(0);
			}

			int row = 0;
			for (size_t pt = chart->L_NumPoints() - 2; pt >= 0 && pt < chart->L_NumPoints() - 1; --pt, ++row)
			{
				point = chart->L_GetPoint(pt);

				InsertChartPoint
					( row
					, point->L_Time()
					, point->L_Open()
					, point->L_High()
					, point->L_Low()
					, point->L_Close()
					, point->L_Volume()
					);
			}
			m_ChartPointsListCtrl.SetRedraw(TRUE);
		}
	}
}

void ChartPointsDlg::InsertChartPoint(int row, time_t time, double open, double high, double low, double close, long long volume)
{
	CString text;

	text.Format("%d", time);
	if (row == 0 && m_ChartPointsListCtrl.GetItemCount() > row)
	{
		CString timeStr;
		timeStr = m_ChartPointsListCtrl.GetItemText(row, 0);
		if (timeStr != text) //if current time is the same as previous rows time we can replace all of the old values with the new values
		{
			m_ChartPointsListCtrl.InsertItem(row, text);
		}
	}
	else if(row == 0 || row <= m_ChartPointsListCtrl.GetItemCount())
	{
		m_ChartPointsListCtrl.InsertItem(row, text);
	}
	else
	{
		m_ChartPointsListCtrl.SetItemText(row, 0, text);
	}

	text.Format("%.2f", open);
	m_ChartPointsListCtrl.SetItemText(row, 1, text);

	text.Format("%.2f", high);
	m_ChartPointsListCtrl.SetItemText(row, 2, text);

	text.Format("%.2f", low);
	m_ChartPointsListCtrl.SetItemText(row, 3, text);

	text.Format("%.2f", close);
	m_ChartPointsListCtrl.SetItemText(row, 4, text);

	text.Format("%d", volume);
	m_ChartPointsListCtrl.SetItemText(row, 5, text);
}

//L_Observer
void ChartPointsDlg::HandleMessage(L_Message const *pMsg)
{
	switch(pMsg->L_Type())
	{
	case L_MsgSymbolChanged::id:
		{
			if (m_Linked)
			{
				SetSymbol(pMsg->L_Symbol());
			}
		}
		break;
	case L_MsgChartSnapshot::id:
		{
			if (summary && !strcmp(pMsg->L_Symbol(), summary->L_Symbol()))
			{
				InsertInitialChart();
			}
		}
		break;
	case L_MsgChartUpdate::id:
		{
			if (summary && !strcmp(pMsg->L_Symbol(), summary->L_Symbol()))
			{
				//removing inserting the new point in favor of iterating over the entire chart again

				//L_MsgChartUpdate const *pMsgCU = static_cast<L_MsgChartUpdate const *>(pMsg);

				//InsertChartPoint(0
				//	, pMsgCU->L_Time()
				//	, pMsgCU->L_Open()
				//	, pMsgCU->L_High()
				//	, pMsgCU->L_Low()
				//	, pMsgCU->L_Close()
				//	, pMsgCU->L_Volume()
				//	);

				InsertInitialChart();
			}
		}
		break;
	}
}

BEGIN_MESSAGE_MAP(ChartPointsDlg, CModelessDialog)
	ON_WM_SIZE()
	ON_COMMAND(ID_FILE_LINK ,OnFileLink)
END_MESSAGE_MAP()


// ChartPointsDlg message handlers

void ChartPointsDlg::OnSize(UINT nType, int cx, int cy)
{
	__super::OnSize(nType, cx, cy);

	ResizeControls();
}

void ChartPointsDlg::ResizeControls()
{
	if (m_hWnd && m_ChartPointsListCtrl.m_hWnd)
	{
		RECT rect;
		GetClientRect(&rect);

		RECT chartPointsRect;
		m_ChartPointsListCtrl.GetWindowRect(&chartPointsRect);
		ScreenToClient(&chartPointsRect);

		rect.top = chartPointsRect.top;

		m_ChartPointsListCtrl.MoveWindow(&rect);
	}
}

void ChartPointsDlg::OnFileLink()
{
	m_Linked = !m_Linked;

	CMenu *menu = GetMenu();	
	menu->CheckMenuItem(ID_FILE_LINK, (m_Linked ? MF_CHECKED : MF_UNCHECKED) );
	
	if (m_Linked)
	{
		SetSymbol(::L_GetFocusedSymbol());
	}
}